// $Id: headers.c 81 2011-04-24 07:37:10Z cedric.shih@gmail.com $
/*
 * Copyright (C) 2010 Cedric Shih <cedric.shih@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <stdlib.h>
#include <string.h>

#include <nio/buffer.h>

#include "common.h"
#include "headers.h"

#include "niohttp/test.h"

static struct niohttp_headers *headers;
static struct niohttp_headers_decoder *decoder;
static struct niohttp_headers_encoder *encoder;
static struct niobuffer *buffer;

static void test_setup(void)
{
	headers = niohttp_headers_new();
	decoder = niohttp_headers_decoder_new();
	encoder = niohttp_headers_encoder_new();
	buffer = niobuffer_new(1024);
}

static void test_teardown(void)
{
	niobuffer_free(buffer);
	niohttp_headers_encoder_free(encoder);
	niohttp_headers_decoder_free(decoder);
	niohttp_headers_free(headers);
}

static void test_init(void)
{
	TEST_ASSERT_NOT_NULL(headers);
	TEST_ASSERT_NOT_NULL(decoder);
	TEST_ASSERT_NOT_NULL(encoder);
	TEST_ASSERT_NOT_NULL(buffer);
}

static struct {
	const char *name;
	const char *value;
} entries[] = {
		{ "Accept-Charset", "utf-8" },
		{ "Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" },
		{ "Content-Length", "348" },
		{ "Cookie", "$Version=1; Skin=new;" },
		{ "Content-Type", "text/html" },
		{ "From", "user@example.com" },
		{ "If-Match", "\"737060cd8c284d8af7ad3082f209582d\"" },
		{ "Upgrade", "HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11" },
		{ "Via", "1.0 fred, 1.1 nowhere.com (Apache/1.1)" },
};

static void test_normal(void)
{
	int rc, i;
	struct niohttp_headers *output;
	const char *value;
	size_t pos;

	niohttp_headers_clear(headers);
	i = niohttp_headers_size(headers);
	TEST_ASSERT_EQUAL_INT(0, i);

	for (i = 0; i < sizeof(entries) / sizeof(entries[0]); i++) {
		rc = niohttp_headers_set(headers,
				entries[i].name, entries[i].value);
		TEST_ASSERT_EQUAL_INT(0, rc);
	}

	i = niohttp_headers_size(headers);
	TEST_ASSERT_EQUAL_INT(sizeof(entries) / sizeof(entries[0]), i);

	niobuffer_clear(buffer);
	rc = niohttp_headers_encoder_setup(encoder);
	TEST_ASSERT_EQUAL_INT(0, rc);

	rc = niohttp_headers_encoder_format(encoder, headers, buffer);
	TEST_ASSERT_EQUAL_INT(0, rc);
	pos = niobuffer_position(buffer);

	niohttp_headers_clear(headers);
	i = niohttp_headers_size(headers);
	TEST_ASSERT_EQUAL_INT(0, i);

	rc = niohttp_headers_decoder_setup(decoder, headers);
	TEST_ASSERT_EQUAL_INT(0, rc);

	niobuffer_flip(buffer);

	rc = niohttp_headers_decoder_parse(decoder, buffer, &output);
	TEST_ASSERT_EQUAL_INT(0, rc);
	TEST_ASSERT_EQUAL_INT(pos, niobuffer_position(buffer));
	TEST_ASSERT_NOT_NULL(output);

	TEST_ASSERT(output == headers);

	i = niohttp_headers_size(headers);
	TEST_ASSERT_EQUAL_INT(sizeof(entries) / sizeof(entries[0]), i);

	for (i = 0; i < sizeof(entries) / sizeof(entries[0]); i++) {
		value = niohttp_headers_get(headers,
				entries[i].name);
		TEST_ASSERT_EQUAL_STRING(entries[i].value, value);
	}
}

TestRef niohttp_headers_codec_test()
{
	EMB_UNIT_TESTFIXTURES(fixtures) {
		new_TestFixture("niohttp_headers_codec_test_init", test_init),
		new_TestFixture("niohttp_headers_codec_test_normal", test_normal),
	};
	EMB_UNIT_TESTCALLER(test_case, "niohttp_headers_codec_test", test_setup, test_teardown, fixtures);
	return (TestRef)&test_case;
}
